package com.zcmyth;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/**
 * 
 * @author Chun Zhang
 */
public class TwoSigmaCodeTestCopyFile {

  private static class Instruction {
    private int dataSetId;
    private int from;
    private int to;

    public Instruction(int dataSetId, int from, int to) {
      this.dataSetId = dataSetId;
      this.from = from;
      this.to = to;
    }

    @Override
    public String toString() {
      return String.format("%d %d %d", dataSetId, from, to);
    }
  }

  private static class DataCenter {
    private Set<Integer> dataIds;
    private int copyTaskCounter;
    private int id;

    public DataCenter(int id, String line) {
      this.id = id;
      dataIds = new HashSet<Integer>();
      String[] ids = line.split(" ");
      for (int i = 0; i < ids.length; i++) {
        dataIds.add(Integer.parseInt(ids[i]));
      }
      copyTaskCounter = 0;
    }

    public Set<Integer> getMissingDataIds(Set<Integer> all) {
      Set<Integer> missingIds = new HashSet<Integer>();
      for (Integer id : all) {
        if (!dataIds.contains(id)) {
          missingIds.add(id);
        }
      }
      return missingIds;
    }

    public Set<Integer> getDataIds() {
      return dataIds;
    }

    public int getCopyTaskNumber() {
      return copyTaskCounter;
    }

    public void addTask() {
      copyTaskCounter++;
    }

    public int getId() {
      return id;
    }
  }

  private static class DataCenters {
    private List<DataCenter> dataCenters;
    private Map<Integer, List<DataCenter>> dataIndex;

    public DataCenters(InputStream inputStream) {
      this.dataIndex = new HashMap<Integer, List<DataCenter>>();
      this.dataCenters = new ArrayList<DataCenter>();

      Scanner scanner = new Scanner(inputStream);
      int size = Integer.parseInt(scanner.nextLine());
      for (int i = 0; i < size; i++) {
        dataCenters.add(new DataCenter(i + 1, scanner.nextLine()));
      }

      for (int i = 0; i < dataCenters.size(); i++) {
        DataCenter center = dataCenters.get(i);
        for (Integer dataSet : center.getDataIds()) {
          List<DataCenter> centers = dataIndex.get(dataSet);
          if (centers == null) {
            centers = new ArrayList<DataCenter>();
            dataIndex.put(dataSet, centers);
          }
          centers.add(center);
        }
      }
    }

    public List<Instruction> resumeAll() {
      List<Instruction> instructions = new ArrayList<Instruction>();
      for (DataCenter center : dataCenters) {
        resumeCenter(center, instructions);
      }
      return instructions;
    }

    private void resumeCenter(DataCenter center, List<Instruction> instructions) {
      for (Integer dataId : center.getMissingDataIds(dataIndex.keySet())) {
        DataCenter sourceCenter = findDataSource(dataId, true);
        instructions.add(new Instruction(dataId, sourceCenter.getId(), center.getId()));
        sourceCenter.addTask();
      }
    }

    private DataCenter findDataSource(int dataId, boolean loadingBalance) {
      List<DataCenter> centers = dataIndex.get(dataId);
      assert (centers != null && centers.size() > 0);
      if (!loadingBalance) {
        return centers.get(0);
      } else {
        DataCenter minCenter = centers.get(0);
        for (int i = 1; i < centers.size(); i++) {
          if (centers.get(i).getCopyTaskNumber() < minCenter.getCopyTaskNumber()) {
            minCenter = centers.get(i);
          }
        }
        return minCenter;
      }
    }
  }

  public static void main(String[] args) {
    DataCenters centers = new DataCenters(System.in);
    printInstructions(centers.resumeAll());
    System.out.println("done");
  }

  private static void printInstructions(List<Instruction> instructions) {
    for (Instruction instruction : instructions) {
      System.out.println(instruction);
    }
  }
}
